package com.filldream.fastboot.core.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.filldream.fastboot.base.entity.SysDept;
import com.filldream.fastboot.base.mapper.SysDeptMapper;
import com.filldream.fastboot.base.request.pc.sysDept.AddDeptSTO;
import com.filldream.fastboot.base.request.pc.sysDept.ModifyDeptSTO;
import com.filldream.fastboot.base.response.pc.DeptTreeDTO;
import com.filldream.fastboot.common.entity.B;
import com.filldream.fastboot.common.entity.ErrorCode;
import com.filldream.fastboot.common.entity.R;
import com.filldream.fastboot.common.util.Assert;
import com.filldream.fastboot.common.util.TransferUtil;
import com.filldream.fastboot.core.LoginHolder;
import com.filldream.fastboot.core.service.SysDeptService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

@Service
@Transactional(rollbackFor = Exception.class)
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements SysDeptService {

    @Override
    public B saveDept(AddDeptSTO addDeptSTO) {
        SysDept dept = TransferUtil.changeToObj(addDeptSTO, SysDept.class);
        dept.setCreateUser( LoginHolder.getPcUserId() );
        checkDeptName(dept,null);

        boolean insert = save(dept);

        return B.checkSuccess(insert);
    }

    @Override
    public R<List<Tree<String>>> tree() {
        Long linkId = LoginHolder.getPcUser().getLinkId();

        linkId = linkId.equals(0L) ? -1L : linkId;

        List<DeptTreeDTO> resultList  = baseMapper.getList();

        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        treeNodeConfig.setWeightKey("deptRank");
        treeNodeConfig.setIdKey("deptId");
        treeNodeConfig.setChildrenKey("children");
        treeNodeConfig.setNameKey("deptName");

        List<Tree<String>> treeNodes = TreeUtil.build(resultList, linkId+"", treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getDeptId()+"");
                    tree.setParentId(treeNode.getParentId()+"");
                    tree.setWeight(treeNode.getDeptRank());
                    tree.setName(treeNode.getDeptName());

                    tree.putExtra("leader",treeNode.getLeader());
                    tree.putExtra("phone",treeNode.getPhone());
                    tree.putExtra("email",treeNode.getEmail());
                    tree.putExtra("status",treeNode.getStatus());
                    tree.putExtra("parentName",treeNode.getParentName());
                    tree.putExtra("createTime",treeNode.getCreateTime());
                    tree.putExtra("deptType",treeNode.getDeptType());
                });

        return R.successd(treeNodes);
    }




    @Override
    public B modifyDept(ModifyDeptSTO modifyDeptSTO) {
        //总公司不得禁用和修改上级
        if( modifyDeptSTO.getDeptId().equals(0L) ){
            Assert.isBoolean( modifyDeptSTO.getParentId() != null && !modifyDeptSTO.getParentId().equals(-1L),ErrorCode.BASE_ERR.reMsg("总公司不允许修改上级部门") );
            Assert.isBoolean( Boolean.FALSE.equals(modifyDeptSTO.getStatus()),ErrorCode.BASE_ERR.reMsg("总公司不得禁用") );
        }

        SysDept newDept = TransferUtil.changeToObj(modifyDeptSTO, SysDept.class);
        newDept.setUpdateUser( LoginHolder.getPcUserId() );
        checkDeptName( newDept,newDept.getDeptId() );

        boolean updateStatus = updateById(newDept);
        //如果禁用的父级部门，则子集部门全部禁用
        if( updateStatus && Boolean.FALSE.equals(modifyDeptSTO.getStatus()) ){
            List<SysDept> childDeptList = getChildDeptList(newDept);
            if(ObjectUtils.isNotEmpty(childDeptList)){
                for (SysDept item : childDeptList) {
                    item.setStatus(modifyDeptSTO.getStatus());
                    item.setUpdateUser(newDept.getUpdateUser());
                }
                updateBatchById(childDeptList);
            }
        }
        return B.checkSuccess(updateStatus);
    }

    @Override
    public B del(Long deptId) {

        //总公司不得删除
        Assert.isBoolean( deptId.equals(0L),ErrorCode.BASE_ERR.reMsg("总公司不得删除") );
        SysDept delDept = getById(deptId);
        Assert.isEmpty(delDept,"部门不存在或已删除");


        delDept.setUpdateUser( LoginHolder.getPcUserId() );
        delDept.setDelFlag(true);
        //删除父级部门则必须先删除子集部门
        List<SysDept> childDeptList = getChildDeptList(delDept);
        Assert.isBoolean( ObjectUtils.isNotEmpty(childDeptList),ErrorCode.BASE_ERR.reMsg("请先删除下级" + childDeptList.size() + "个部门，再删除 " +delDept.getDeptName()) );

        return B.checkSuccess(updateById(delDept));
    }

    public void checkDeptName( SysDept sysDept,Long selfId){

        QueryWrapper<SysDept> sql = new QueryWrapper<>();
        sql.eq("del_flag", 0);
        if( sysDept.getParentId() != null ){
            sql.eq("parent_id", sysDept.getParentId());
        }

        if(StringUtils.isNotBlank(sysDept.getDeptName())){
            sql.eq("dept_name", sysDept.getDeptName());
        }

        if( selfId != null ){
            sql.ne( "dept_id",selfId );
        }

        Assert.isBoolean(count(sql) > 0, ErrorCode.BASE_ERR.reMsg( sysDept.getDeptName() + " 已存在"));
    }

    public List<SysDept> getChildDeptList( SysDept sysDept){
        return list(
                new QueryWrapper<SysDept>()
                        .eq("parent_id", sysDept.getDeptId())
                        .eq("del_flag", 0)
        );
    }


}
